/*******************************************************************************
 * Copyright (c) 2024-10-29 @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@gmail.com">Tyler Chen</a> - initial API and implementation.
 ******************************************************************************/
package org.iff.util;

import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

import static org.objectweb.asm.Opcodes.*;

/**
 * 自动实现接口适配，主要使用场景是为了解耦，使用时需要调用 new$ 或 target$(Object target) 方法来创建新实例，性能经过优化，比直接使用反射要快很多。
 * <pre>
 * #1.例子：
 * #1.1.定义一个接口，并且必须有target$()方法，target$(Object target) 与new$方法必须至少存在一个，其他的方法必须是适配目标类的方法(支持目标类的静态)，如果有泛型请使用Object对象
 * {@code
 * public interface TestMap {
 *   Object target$();                      //此方法必须
 *   TestMap target$(Object target);        //设置适配的目标对象，此方法与 new$ 方法【必须】存在一个
 *   TestMap new$();                        //该方法可以用于创建Target的实例，支持方法的重载，此方法与 target$(Object target) 方法【必须】存在一个
 *   TestMap new$(int initialCapacity);     //该方法可以用于创建Target的实例，支持方法的重载，此方法与 target$(Object target) 方法【必须】存在一个
 *   Object get(Object key);                //泛型类型，使用 Object 类型
 *   Object put(Object key, Object value);  //泛型类型，使用 Object 类型
 * }
 * }
 * #1.2.自动实现TestMap接口，并适配HashMap，创建新的实例时需要调用new$()方法，或者调用target$(Object target)方法
 * {@code
 * TestMap map_0 = adapter(TestHashMap.class, HashMap.class.getName()).new$();
 * TestMap map_1 = adapter(TestHashMap.class, HashMap.class.getName()).target$(new HashMap<>());
 * }
 * #1.3.调用接口
 * {@code
 * map.put("a", "1");
 * System.out.println(map.get("a")); //Output: 1
 * System.out.println(map.target$()); //Output: {a=1}
 * }
 * #2.类型自动装配及类型自动转换
 * 如 TargetObject 有一个方法：TargetObject setInstance(TargetObject instance);
 * Adapter 接口应定义为：TargetObjectAdapter setInstance(TargetObjectAdapter instance);
 * #2.1.返回类型 TargetObjectAdapter 在调用 TargetObject.setInstance 后自动把结果 TargetObject 装配为 TargetObjectAdapter 类型。
 * #2.2.参数类型 TargetObjectAdapter 在调用 TargetObject.setInstance 前自动调用 TargetObjectAdapter.target$() 方法获取 TargetObject 类型。
 * #2.3.类型自动装配及类型自动转换，会自动检测已经定义的 Adapter 类，如果存在则使用，否则需要为指定的类型创建 Adapter 类。
 * </pre>
 *
 * @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>
 * @since 2024-10-29
 */
public class AdapterUtil {
    private static final String targetFieldName = "target_";
    private static final String getSetTargetMethodName = "target$";
    private static final String newInstanceMethodName = "new$";
    private static final Map<Type, Type> adapterInterfaceToTarget = new HashMap<>();
    private static final Map<Type, Class<?>> adapterClass = new HashMap<>();
    private static final Map<Class<?>, Object> adapterInstance = new HashMap<>();
    private static final MyClassLoader classLoader = new MyClassLoader();
    private static final String[] debugMarker = new String[]{"debug"};

    public static void adapter(Map<Class<?>/*adapterInterface*/, String/*targetClassName*/> adapterMap) {
        if (adapterMap == null || adapterMap.isEmpty()) {
            return;
        }
        //Register adapter first
        for (Map.Entry<Class<?>, String> entry : adapterMap.entrySet()) {
            adapterInterfaceToTarget.put(toType(Objects.requireNonNull(entry.getKey())), toType(Objects.requireNonNull(entry.getValue())));
        }
        //adapter all
        for (Map.Entry<Class<?>, String> entry : adapterMap.entrySet()) {
            Class<?> adapterInterface = entry.getKey();
            final Type adapterInterfaceType = toType(adapterInterface);
            final Type targetClassType = toType(entry.getValue());
            final Type adapterClassType = getAdapterClassType(adapterInterfaceType, targetClassType);
            adapter(adapterInterface, adapterInterfaceType, targetClassType, adapterClassType);
        }
        for (Map.Entry<Class<?>, String> entry : adapterMap.entrySet()) {
            adapter(entry.getKey(), entry.getValue());
        }
    }

    static Type getAdapterClassType(Type adapterInterfaceType, Type targetClassType) {
        String adapterClassName = adapterInterfaceType.getClassName() + "_" + targetClassType.getClassName().replace('.', '_').replace('/', '_');
        return toType(adapterClassName);
    }

    public static <T> T adapter(final Class<T> adapterInterface, final String targetClassName) {
        if (adapterInterface == null || StringUtils.isBlank(targetClassName)) {
            return null;
        }
        {
            Object obj = adapterInstance.get(adapterInterface);
            if (obj != null) {
                return (T) obj;
            }
        }
        final Type adapterInterfaceType = toType(adapterInterface);
        final Type targetClassType = toType(targetClassName);
        final Type adapterClassType = getAdapterClassType(adapterInterfaceType, targetClassType);
        {
            Class<?> aClass = adapterClass.get(adapterClassType);
            aClass = aClass != null ? aClass : adapter(adapterInterface, adapterInterfaceType, targetClassType, adapterClassType);
            if (aClass != null) {
                try {
                    Object obj = aClass.getConstructor(new Class[0]).newInstance();
                    adapterInstance.put(adapterInterface, obj);
                    return (T) obj;
                } catch (Exception e) {
                    Exceptions.runtime("Can not create instance for adapter class: " + aClass.getName(), e);
                }
            }
        }
        return null;
    }

    static synchronized <T> Class<T> adapter(final Class<T> adapterInterface, final Type adapterInterfaceType, final Type targetClassType, final Type adapterClassType) {
        {
            Class<?> aClass = adapterClass.get(adapterClassType);
            if (aClass != null) {
                return (Class<T>) aClass;
            }
        }
        final Type objectType = toType(Object.class);
        final Class<?> targetClass;
        try {
            targetClass = Class.forName(targetClassType.getClassName());
        } catch (Exception e) {
            Exceptions.runtime("Can not find class: " + targetClassType.getClassName(), e);
            return null;
        }
        {//set cache first
            adapterInterfaceToTarget.put(adapterInterfaceType, targetClassType);
        }
        //Generation Adaper Class
        {
            final org.objectweb.asm.commons.Method adapterConstructor = new org.objectweb.asm.commons.Method(
                    "<init>", Type.VOID_TYPE, new Type[]{targetClassType}
            );
            final org.objectweb.asm.commons.Method emptyConstructor = new org.objectweb.asm.commons.Method(
                    "<init>", Type.VOID_TYPE, new Type[]{}
            );
            final org.objectweb.asm.commons.Method getTargetObjectMethod = new org.objectweb.asm.commons.Method(
                    getSetTargetMethodName, objectType, new Type[]{}
            );
            final Method[] adapterInterfaceMethods = adapterInterface.getMethods();
            final Method[] targetClassMethods = targetClass.getMethods();
            // (1) 创建ClassWriter对象
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS /*自动计算局部变量和操作数栈大小*/);
            cw.visit(V1_8,                                                  // version
                    ACC_PUBLIC,                                             // access
                    adapterClassType.getInternalName(),                     // name
                    null,                                                   // signature
                    objectType.getInternalName(),                          // superName
                    new String[]{adapterInterfaceType.getInternalName()}   // interfaces
            );
            // (2) 添加字段
            {
                FieldVisitor fv1 = cw.visitField(ACC_PRIVATE, targetFieldName, targetClassType.getDescriptor(), null, null);
                fv1.visitEnd();
            }
            // (3) 无参构造函数()
            {
                GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, emptyConstructor, null, null, cw);
                mg.loadThis();
                mg.invokeConstructor(objectType, emptyConstructor);
                mg.returnValue();
                mg.endMethod();
            }
            {//带参构造函数()
                GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, adapterConstructor, null, null, cw);
                mg.loadThis();
                mg.invokeConstructor(objectType, emptyConstructor);
                mg.loadThis();
                mg.loadArg(0);
                mg.putField(adapterClassType, targetFieldName, targetClassType);
                mg.returnValue();
                mg.endMethod();
            }
            // (4) 实现接口方法
            {//实现实例创建的方法: new$
                for (Method adaptInterfaceMethod : adapterInterfaceMethods) {
                    if (Modifier.isStatic(adaptInterfaceMethod.getModifiers())) {
                        continue;
                    }
                    if (!adaptInterfaceMethod.getName().equals(newInstanceMethodName)) {
                        continue;
                    }
                    if (adaptInterfaceMethod.getReturnType() != adapterInterface) {
                        Exceptions.runtime("The return type of the method new$ must be the interface itself: " + adapterInterface.getName());
                        return null;
                    }
                    org.objectweb.asm.commons.Method adapterMethod = org.objectweb.asm.commons.Method.getMethod(adaptInterfaceMethod);
                    org.objectweb.asm.commons.Method constructor = new org.objectweb.asm.commons.Method("<init>", Type.VOID_TYPE, adapterMethod.getArgumentTypes());
                    Constructor targetOriginMethod = getConstructor(targetClassType, adaptInterfaceMethod, adapterInterfaceToTarget);
                    if (targetOriginMethod == null) {
                        Exceptions.runtime("can not find constructor: " + adaptInterfaceMethod + " in " + targetClassType);
                        return null;
                    }

                    GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, adapterMethod, null, null, cw);
                    mg.loadThis();
                    Map<String, Integer> variableIndex = new HashMap<>();
                    //检查参数类型，如果有 Adapter 类型就先进行转换
                    {
                        Class<?>[] adaptParameterTypes = adaptInterfaceMethod.getParameterTypes();
                        Class<?>[] targetParameterTypes = targetOriginMethod.getParameterTypes();
                        for (int i = 0; i < adaptParameterTypes.length; i++) {
                            Type adaptParamterType = toType(adaptParameterTypes[i]);
                            if (!adapterInterfaceToTarget.containsKey(adaptParamterType)) {
                                continue;
                            }
                            Type targetParameterType = toType(targetParameterTypes[i]);
                            mg.loadArg(i);
                            mg.invokeInterface(adaptParamterType, getTargetObjectMethod);//Invoke get target method
                            mg.checkCast(targetParameterType);
                            int localIndex = mg.newLocal(targetParameterType);
                            mg.storeLocal(localIndex);
                            variableIndex.put("parameter_" + i, localIndex);
                        }
                    }
                    mg.newInstance(targetClassType);//new Target
                    mg.dup();
                    //把参数压栈
                    {
                        Class<?>[] adaptParameterTypes = adaptInterfaceMethod.getParameterTypes();
                        for (int i = 0; i < adaptParameterTypes.length; i++) {
                            Type adaptParamterType = toType(adaptParameterTypes[i]);
                            if (adapterInterfaceToTarget.containsKey(adaptParamterType)) {
                                mg.loadLocal(variableIndex.get("parameter_" + i));
                            } else {
                                mg.loadArg(i);
                            }
                        }
                    }
                    mg.invokeConstructor(targetClassType, constructor);//Invoke Target Constructor
                    int instanceIndex = mg.newLocal(targetClassType);
                    mg.storeLocal(instanceIndex, targetClassType);
                    {//创建adapterClassType实例，并设置字段targetFieldName
                        mg.newInstance(adapterClassType);//new Adapter
                        mg.dup();
                        mg.invokeConstructor(adapterClassType, emptyConstructor);//Invoke Adapter Constructor
                        int resultIndex = mg.newLocal(adapterClassType);
                        mg.storeLocal(resultIndex);
                        mg.loadLocal(resultIndex);
                        mg.loadLocal(instanceIndex);
                        mg.putField(adapterClassType, targetFieldName, targetClassType);//set targetFieldName
                        mg.loadLocal(resultIndex);
                    }
                    mg.returnValue();
                    mg.endMethod();
                }
            }
            {//实现默认的接口方法 target$()
                for (Method adaptInterfaceMethod : adapterInterfaceMethods) {
                    if (Modifier.isStatic(adaptInterfaceMethod.getModifiers())) {
                        continue;
                    }
                    if (!adaptInterfaceMethod.getName().equals(getSetTargetMethodName)) {
                        continue;
                    }
                    if (adaptInterfaceMethod.getParameterCount() != 0) {
                        continue;
                    }
                    org.objectweb.asm.commons.Method getTargetObject = org.objectweb.asm.commons.Method.getMethod(adaptInterfaceMethod);
                    GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, getTargetObject, null, null, cw);
                    mg.loadThis();
                    mg.getField(adapterClassType, targetFieldName, targetClassType);
                    mg.returnValue();
                    mg.endMethod();
                    break;
                }
            }
            {//实现默认的接口方法 target$(Object target)
                for (Method adaptInterfaceMethod : adapterInterfaceMethods) {
                    if (Modifier.isStatic(adaptInterfaceMethod.getModifiers())) {
                        continue;
                    }
                    if (!adaptInterfaceMethod.getName().equals(getSetTargetMethodName)) {
                        continue;
                    }
                    if (adaptInterfaceMethod.getParameterCount() != 1 || adaptInterfaceMethod.getParameterTypes()[0] != Object.class) {
                        continue;
                    }
                    org.objectweb.asm.commons.Method getTargetObject = org.objectweb.asm.commons.Method.getMethod(adaptInterfaceMethod);
                    GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, getTargetObject, null, null, cw);
                    mg.loadThis();
                    mg.loadArg(0);
                    mg.checkCast(targetClassType);
                    int instanceIndex = mg.newLocal(targetClassType);
                    mg.storeLocal(instanceIndex, targetClassType);
                    {//创建adapterClassType实例，并设置字段targetFieldName
                        mg.newInstance(adapterClassType);//new Adapter
                        mg.dup();
                        mg.invokeConstructor(adapterClassType, emptyConstructor);//Invoke Adapter Constructor
                        int resultIndex = mg.newLocal(adapterClassType);
                        mg.storeLocal(resultIndex);
                        mg.loadLocal(resultIndex);
                        mg.loadLocal(instanceIndex);
                        mg.putField(adapterClassType, targetFieldName, targetClassType);//set targetFieldName
                        mg.loadLocal(resultIndex);
                    }
                    mg.returnValue();
                    mg.endMethod();
                    break;
                }
            }
            {//实现接口的其他方法
                for (Method adaptInterfaceMethod : adapterInterfaceMethods) {
                    if (Modifier.isStatic(adaptInterfaceMethod.getModifiers())) {
                        continue;
                    }
                    if (adaptInterfaceMethod.getName().equals(getSetTargetMethodName)) {
                        continue;
                    }
                    if (adaptInterfaceMethod.getName().equals(newInstanceMethodName)) {
                        continue;
                    }
                    org.objectweb.asm.commons.Method adapterMethod = org.objectweb.asm.commons.Method.getMethod(adaptInterfaceMethod);
                    MyMethod targetOriginMethod = getMethod(targetClass, targetClassMethods, adapterInterface, adaptInterfaceMethod, adapterInterfaceToTarget);
                    if (targetOriginMethod == null) {
                        Exceptions.runtime("can not find method: " + adaptInterfaceMethod + " in " + targetClassType);
                        return null;
                    }
                    org.objectweb.asm.commons.Method targetMethod = org.objectweb.asm.commons.Method.getMethod(targetOriginMethod.method);

                    GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, adapterMethod, null, null, cw);
                    mg.loadThis();
                    Map<String, Integer> variableIndex = new HashMap<>();
                    //检查参数类型，如果有 Adapter 类型就先进行转换
                    {
                        Class<?>[] adaptParameterTypes = adaptInterfaceMethod.getParameterTypes();
                        Class<?>[] targetParameterTypes = targetOriginMethod.method.getParameterTypes();
                        for (int i = 0; i < adaptParameterTypes.length; i++) {
                            Type adaptParamterType = toType(adaptParameterTypes[i]);
                            if (!adapterInterfaceToTarget.containsKey(adaptParamterType)) {
                                continue;
                            }
                            Type targetParameterType = toType(targetParameterTypes[i]);
                            mg.loadArg(i);
                            mg.invokeInterface(adaptParamterType, getTargetObjectMethod);
                            mg.checkCast(targetParameterType);
                            int localIndex = mg.newLocal(targetParameterType);
                            mg.storeLocal(localIndex);
                            variableIndex.put("parameter_" + i, localIndex);
                        }
                    }
                    //把参数压栈
                    {
                        mg.loadThis();
                        mg.getField(adapterClassType, targetFieldName, targetClassType);
                        Class<?>[] adaptParameterTypes = adaptInterfaceMethod.getParameterTypes();
                        for (int i = 0; i < adaptParameterTypes.length; i++) {
                            Type adaptParamterType = toType(adaptParameterTypes[i]);
                            if (adapterInterfaceToTarget.containsKey(adaptParamterType)) {
                                mg.loadLocal(variableIndex.get("parameter_" + i));
                            } else {
                                mg.loadArg(i);
                            }
                        }
                    }
                    //调用 targetMethod
                    if (Modifier.isStatic(targetOriginMethod.method.getModifiers())) {
                        mg.invokeStatic(targetClassType, targetMethod);
                    } else {
                        if (targetClass.isInterface()) {
                            mg.invokeInterface(targetClassType, targetMethod);
                        } else {
                            mg.invokeVirtual(targetClassType, targetMethod);
                        }
                    }
                    if (adapterMethod.getReturnType().equals(objectType)) {//返回类型是 Object类型，就不用转换了
                        //do nothing
                    }
                    //类型转换：如果返回类型不一致。如：应该返回 Adapter，但返回的是 Target，此时需要找到 Adapter 的实现类，然后调用其构造函数，将 Target 转换成 Adapter
                    else if (!adapterMethod.getReturnType().equals(targetMethod.getReturnType())) {
                        if (adaptInterfaceMethod.getReturnType() == adapterInterface &&
                                Void.TYPE.equals(targetOriginMethod.method.getReturnType())
                        ) {//target 方法返回的是 void ，但 adapter 方法返回的是自身
                            mg.loadThis();
                            //mg.checkCast(adapterClassType);
                        } else {
                            mg.checkCast(targetOriginMethod.returnType);
                            int forTypeCastIndex = mg.newLocal(targetOriginMethod.returnType);
                            mg.storeLocal(forTypeCastIndex, targetOriginMethod.returnType);
                            Type adapterClassTypeForCast = getAdapterClassType(adapterMethod.getReturnType(), targetOriginMethod.returnType);
                            mg.newInstance(adapterClassTypeForCast);
                            mg.dup();
                            mg.loadLocal(forTypeCastIndex);
                            org.objectweb.asm.commons.Method constructor = new org.objectweb.asm.commons.Method("<init>", Type.VOID_TYPE, new Type[]{targetOriginMethod.returnType});
                            mg.invokeConstructor(adapterClassTypeForCast, constructor);
                            int resultIndex = mg.newLocal(adapterClassTypeForCast);
                            mg.storeLocal(resultIndex);
                            mg.loadLocal(resultIndex);
                        }
                    }
                    //返回值
                    mg.returnValue();
                    mg.endMethod();
                }
            }
            cw.visitEnd();
            // (5) 生成字节码
            byte[] code = cw.toByteArray();
            {
                Textifier textifier = new Textifier();
                TraceClassVisitor traceClassVisitor = new TraceClassVisitor(null, textifier, new PrintWriter(System.out));
                ClassReader cr = new ClassReader(code);
                cr.accept(traceClassVisitor, 0);
            }
            // (6) 加载到JVM中
            // 自定义类加载器用于加载动态生成的类
            try {
                Class<?> dynamicClass = classLoader.defineClass(adapterClassType.getClassName(), code);
                {//set cache
                    adapterClass.put(adapterClassType, dynamicClass);
                }
                return (Class<T>) dynamicClass;
            } catch (Exception e) {
                Exceptions.runtime("create adapter error:", e);
            }
        }
        return null;
    }

    static Type toType(Class<?> clazz) {
        return Type.getType(clazz);
    }

    static Type toType(String className) {
        return Type.getObjectType(className.replace('.', '/'));
    }

    static class MyClassLoader extends ClassLoader {
        public MyClassLoader() {
            super(AdapterUtil.class.getClassLoader());
        }

        public Class<?> defineClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }

    static class MyMethod {
        private Method method;
        private Type returnType;

        public MyMethod(Method method, Type returnType) {
            this.method = method;
            this.returnType = returnType;
        }
    }

    static MyMethod getMethod(Class<?> targetClass, Method[] targetClassMethods, Class<?> adapterInterface, Method adapterMethod, Map<Type/*adapterInterfaceType*/, Type/*targetType*/> adapterInterfaceToTarget) {
        for (Method declaredMethod : targetClassMethods) {
            //1.如果方法名称不匹配，则跳过
            if (!declaredMethod.getName().equals(adapterMethod.getName())) {
                continue;
            }
            //2.如果参数个数不匹配，则跳过
            if (declaredMethod.getParameterCount() != adapterMethod.getParameterCount()) {
                continue;
            }
            //用于调试
            if (declaredMethod.getName().equals(debugMarker[0])) {
                declaredMethod.getName().equals(debugMarker[0]);
            }

            Class<?> declaredMethodReturnType = declaredMethod.getReturnType(), adapterMethodReturnType = adapterMethod.getReturnType();
            Type adapterReturnType = toType(adapterMethodReturnType);
            Type targetRetrunType = toType(declaredMethodReturnType);

            //3.检查方法返回类型的匹配
            if (declaredMethodReturnType != adapterMethodReturnType) {
                boolean isReturnTypeMatch = false;
                //3.1.如果返回类型是 Object 类型，那么可以适配为任意类型
                if (Void.TYPE.equals(declaredMethodReturnType)) {
                    if (adapterInterface == adapterMethodReturnType) {
                        isReturnTypeMatch = true;
                        targetRetrunType = adapterReturnType;
                    }
                } else if (adapterMethodReturnType == Object.class) {
                    isReturnTypeMatch = true;
                }
                //3.2.如果返回的类型是targetClassType的父类，那么该类型可以转换为targetClassType
                if (!isReturnTypeMatch) {
                    if (declaredMethodReturnType == declaredMethod.getDeclaringClass()) {
                        isReturnTypeMatch = true;
                        targetRetrunType = toType(targetClass);
                    } else if (declaredMethodReturnType.isAssignableFrom(targetClass)) {
                        isReturnTypeMatch = true;
                        targetRetrunType = toType(targetClass);
                    }
                }
                //3.3.如果返回类型不是一个 Adapter 类，那么不适配
                if (!isReturnTypeMatch && !adapterInterfaceToTarget.containsKey(adapterReturnType)) {
                    continue;
                }
                try {
                    if (!isReturnTypeMatch) {
                        //3.4.如果返回的类型是某一个Adapter 类的父类，那么该类型可以转换为该 Adapter 类
                        Type returnAdapterTargetType = adapterInterfaceToTarget.get(adapterReturnType);
                        Class<?> returnAdapterTargetClass = Class.forName(returnAdapterTargetType.getClassName());
                        if (!declaredMethodReturnType.isAssignableFrom(returnAdapterTargetClass)) {
                            continue;
                        } else {
                            targetRetrunType = returnAdapterTargetType;
                        }
                    }
                } catch (Exception e) {
                }
            }
            //4.检查参数类型是否匹配
            Class<?>[] targetParameterTypes = declaredMethod.getParameterTypes();
            Class<?>[] adapterParameterTypes = adapterMethod.getParameterTypes();
            boolean parameterTypeMatch = true;
            for (int i = 0; parameterTypeMatch && i < targetParameterTypes.length; i++) {
                if (targetParameterTypes[i] == adapterParameterTypes[i]) {
                    continue;
                }
                Type targetParameterType = toType(targetParameterTypes[i]);
                Type adapterParameterType = toType(adapterParameterTypes[i]);
                //4.1.如果参数是一个 Adapter 类型，那么需要检查其目标类型是否匹配
                if (adapterInterfaceToTarget.containsKey(adapterParameterType)
                        && targetParameterType.equals(adapterInterfaceToTarget.get(adapterParameterType))
                ) {
                    continue;
                } else {
                    parameterTypeMatch = false;
                }
            }
            if (!parameterTypeMatch) {
                continue;
            }
            return new MyMethod(declaredMethod, targetRetrunType);
        }
        return null;
    }

    static Constructor getConstructor(Type targetClassType, Method adapterMethod, Map<Type/*adapterInterfaceType*/, Type/*targetType*/> adapterInterfaceToTarget) {
        Class<?> cls = null;
        try {
            cls = Class.forName(targetClassType.getClassName());
        } catch (Exception e) {
        }
        for (Constructor declaredMethod : cls.getDeclaredConstructors()) {
            if (declaredMethod.getParameterCount() != adapterMethod.getParameterCount()) {
                continue;
            }
            Class<?>[] targetParameterTypes = declaredMethod.getParameterTypes();
            Class<?>[] adapterParameterTypes = adapterMethod.getParameterTypes();
            for (int i = 0; i < targetParameterTypes.length; i++) {
                if (targetParameterTypes[i] == adapterParameterTypes[i]) {
                    continue;
                }
                Type targetParameterType = toType(targetParameterTypes[i]);
                Type adapterParameterType = toType(adapterParameterTypes[i]);
                if (adapterInterfaceToTarget.containsKey(adapterParameterType)
                        && targetParameterType.equals(adapterInterfaceToTarget.get(adapterParameterType))
                ) {
                    continue;
                } else {
                    break;
                }
            }
            return declaredMethod;
        }
        return null;
    }

}
